﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Permissions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace AIStudio.Wpf.ECharts.Controls
{
    /// <summary>
    /// Echart.xaml 的交互逻辑
    /// </summary>
    public partial class LineEchart : UserControl
    {

        public static readonly DependencyProperty LabelsProperty = DependencyProperty.Register(
            "Labels", typeof(LabelClass), typeof(LineEchart), new PropertyMetadata(null, OnLabelsPropertyCallback));
        public LabelClass Labels
        {
            get { return (LabelClass)GetValue(LabelsProperty); }
            set { SetValue(LabelsProperty, value); }
        }

        private static void OnLabelsPropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var chart = (LineEchart)d;
            chart.OnLabelsPropertyCallback(e.NewValue as LabelClass, e.OldValue as LabelClass);
        }

        private void OnLabelsPropertyCallback(LabelClass newvalue, LabelClass oldvalue)
        {
            if (oldvalue != null)
            {
                oldvalue.Labels.CollectionChanged -= Labels_CollectionChanged;
            }
            if (newvalue != null)
            {
                newvalue.Labels.CollectionChanged += Labels_CollectionChanged;
            }
        }

        public static readonly DependencyProperty ValuesCollectionProperty = DependencyProperty.Register(
                  "ValuesCollection", typeof(ObservableCollection<ValuesClass>), typeof(LineEchart), new PropertyMetadata(null, OnValuesCollectionPropertyCallback));
        public ObservableCollection<ValuesClass> ValuesCollection
        {
            get { return (ObservableCollection<ValuesClass>)GetValue(ValuesCollectionProperty); }
            set { SetValue(ValuesCollectionProperty, value); }
        }

        private static void OnValuesCollectionPropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var chart = (LineEchart)d;
            chart.OnValuesCollectionPropertyCallback(e.NewValue as ObservableCollection<LabelClass>, e.OldValue as ObservableCollection<LabelClass>);
        }

        private void OnValuesCollectionPropertyCallback(ObservableCollection<LabelClass> newvalue, ObservableCollection<LabelClass> oldvalue)
        {
            if (oldvalue != null)
            {
                oldvalue.CollectionChanged -= LineEchart_CollectionChanged;
            }
            if (newvalue != null)
            {
                newvalue.CollectionChanged += LineEchart_CollectionChanged;
            }
            DrawLine();
        }
        private void LineEchart_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            DrawLine();
        }

        public LineEchart()
        {
            InitializeComponent();
            Web.ObjectForScripting = new WebAdapter(Web);
            Web.Navigate(new Uri(System.AppDomain.CurrentDomain.BaseDirectory + "Htmls\\BasicLineChart.html"));
            SizeChanged += LineEchart_SizeChanged;

            this.Loaded += LineEchart_Loaded;
        }

        private void LineEchart_Loaded(object sender, RoutedEventArgs e)
        {
            Task.Run(async delegate
            {
                await Task.Delay(1000);

                Dispatcher.Invoke(() => DrawLine());
            });

        }

        private void LineEchart_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (!IsLoaded) return;

            try
            {
                Web.InvokeScript("jsSetSize", (int)(this.ActualWidth * 0.97), (int)(this.ActualHeight * 0.97));
                DrawLine();
            }
            catch { }
        }

        private void DrawLine()
        {
            try
            {
                if (!IsLoaded) return;

                if (Labels != null)
                {
                    Web.InvokeScript("jsSetXDatas", Newtonsoft.Json.JsonConvert.SerializeObject(Labels.Labels));
                }

                if (ValuesCollection != null)
                {
                    foreach (var values in ValuesCollection)
                    {
                        values.Values.CollectionChanged -= Values_CollectionChanged;
                        values.Values.CollectionChanged += Values_CollectionChanged;
                        Web.InvokeScript("jsSetYDatas", Newtonsoft.Json.JsonConvert.SerializeObject(values.Values), values.Type, ValuesCollection.IndexOf(values));
                    }
                }
            }
            catch(Exception ex)
            {

            }
        }

        private void Values_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            var values = sender as ObservableCollection<object>;
            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems)
                {
                    Web.InvokeScript("jsShiftYData", item, ValuesCollection?.Select(p => p.Values).ToList().IndexOf(values));
                }
            }
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems)
                {
                    Web.InvokeScript("jsPushYData", item, ValuesCollection?.Select(p => p.Values).ToList().IndexOf(values));
                }
            }
        }

        private void Labels_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            var values = sender as ObservableCollection<object>;
            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems)
                {
                    Web.InvokeScript("jsShiftXData", item);
                }
            }
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems)
                {
                    Web.InvokeScript("jsPushXData", item);
                }
            }
        }

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        [System.Runtime.InteropServices.ComVisible(true)]//给予权限并设置可见
        public class WebAdapter
        {
            WebBrowser web;
            public WebAdapter(WebBrowser web)
            {
                this.web = web;
            }
            public void ShowMsg(string Msg)
            {
                MessageBox.Show(Msg);
            }
        }
    }





    public class ValuesClass : BindableBase
    {
        private ObservableCollection<object> _values = new ObservableCollection<object>();
        public ObservableCollection<object> Values
        {
            get { return _values; }
            set
            {
                if (_values != value)
                {
                    SetProperty(ref _values, value);
                }
            }
        }

        public string Type { get; set; } = "line";
    }

    public class LabelClass: BindableBase
    {
        private ObservableCollection<string> _labels = new ObservableCollection<string>();
        public ObservableCollection<string> Labels
        {
            get { return _labels; }
            set
            {
                if (_labels != value)
                {
                    SetProperty(ref _labels, value);
                }
            }
        }
    }
}
